package com.hx.localmiaosha.service.imp;

import com.alibaba.fastjson.JSON;
import com.hx.common.common.enums.ResultStatus;
import com.hx.common.constant.GoodServerConstant;
import com.hx.common.domain.MiaoshaGoods;
import com.hx.common.exception.GlobleException;
import com.hx.common.to.OrderMessageTo;
import com.hx.common.to.RedisGoodsTo;
import com.hx.common.vo.GoodsVo;
import com.hx.localmiaosha.dao.LocalGoodsDao;
import com.hx.localmiaosha.service.LocalMiaoshaGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

/**
 * @Author wonghiu
 * @Date 2021/6/4 19:18
 * @Version 1.0.1
 */
@Component
@Slf4j
public class LocalGoodsServiceImp implements LocalMiaoshaGoodsService {
    @Autowired
    private LocalGoodsDao goodsDao;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public List<GoodsVo> listGoodsVo() {
        List<GoodsVo> goodsVos = goodsDao.listGoodsVo();
        return goodsVos;
    }

    @Override
    public List<GoodsVo> listMiaoShaGoodsVo() {

        List<GoodsVo> goodsVos = goodsDao.listGoodsVo();
//        goodsVos.stream().forEach(goodsVo -> {
//            String redisGoodsTo = redisTemplate.opsForValue().get(GoodServerConstant.GOODS_INFO_PREFIX + goodsVo.getId());
//            goodsVo.setRandomCode(JSON.parseObject(redisGoodsTo, RedisGoodsTo.class).getRandomCode());
//        });
        return goodsVos;
    }

    @Override
    public Integer check() {
        return 1;
    }

    @Override
    public MiaoshaGoods getGoodsById(Long goodsId) {
        return goodsDao.getMiaoshaGoodsVoByGoodsId(goodsId);
    }

    @Override
    public boolean releaseStock(OrderMessageTo orderMessageTo) {
        Long goodsId = orderMessageTo.getGoodsId();
        Integer countGoods = orderMessageTo.getCountGoods();
        goodsDao.releaseStock(goodsId, countGoods);
        return true;
    }

    @Override
    @Transactional
    // 使用乐观锁
    public boolean reduceStock(OrderMessageTo orderMessageTo) {
        Long goodsId = orderMessageTo.getGoodsId();
        MiaoshaGoods miaoshaGoods = goodsDao.getMiaoshaGoodsVoByGoodsId(goodsId);
        int res = 0;
        if (miaoshaGoods.getStockCount()>0) {
            res = goodsDao.reduceStock(miaoshaGoods);

        }
        return res>0;
    }

    @Override
    public GoodsVo getGoodsVoByGoodsId(long goodsId) {

        return goodsDao.getGoodsVoByGoodsId(goodsId);
    }

    // 返回带随机码的秒杀商品信息
    @Override
    public GoodsVo getMiaoShaGoodsVoByGoodsId(long goodsId) {
        GoodsVo goodsVo = goodsDao.getGoodsVoByGoodsId(goodsId);
        return goodsVo;
    }

    @Override
    public void submitGoods2Cache() {
        // 获取所有商品
        List<GoodsVo> goodsVos = goodsDao.listGoodsVo();
        goodsVos.forEach(goodsVo -> {
            // 生成随机码
            String randomCode = UUID.randomUUID().toString().replace("-", "");
//            goodsVo.setRandomCode(randomCode);
            RedisGoodsTo redisGoodsTo = new RedisGoodsTo();
            redisGoodsTo.setEndDate(goodsVo.getEndDate());
            redisGoodsTo.setStartDate(goodsVo.getStartDate());
            redisGoodsTo.setGoodsId(goodsVo.getId());
            redisGoodsTo.setRandomCode(randomCode);
            redisGoodsTo.setGoodsName(goodsVo.getGoodsName());
            redisGoodsTo.setMiaoshaPrice(goodsVo.getMiaoshaPrice());
            // 将秒杀商品TO写入redis
            redisTemplate.opsForValue().set(GoodServerConstant.GOODS_INFO_PREFIX + goodsVo.getId(), JSON.toJSONString(redisGoodsTo));
            // 将库存+id放到缓存中，作为分布式锁的信号量
            RSemaphore semaphore = redissonClient.getSemaphore(GoodServerConstant.GOODS_STOCK_PREFIX + goodsVo.getId());
            log.info(""+goodsVo.getStockCount()+goodsVo.getId());
            semaphore.trySetPermits(goodsVo.getStockCount());

        });
    }

}
